﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.IO;
using System.ComponentModel;
using Compiled_Tests.Utils;
using System.Media;

namespace GUI.Custom_Classes
{
    /// <summary>
    /// Interaction logic for AddRules.xaml
    /// </summary>
    public partial class AddRules : Window
    {
        #region Attributes

        /// <summary>
        /// Root window element used for refreshing viewing panes and loading
        /// rule editing info.
        /// </summary>
        private Window1 root;

        public string save { get; private set; }
        public string name { get; private set; }

        /// <summary>
        /// Offset values for scrollbars for all 3 viewing panes.
        /// </summary>
        private double precondVOffset = 0;
        private double precondHOffset = 0;
        private double actionVOffset = 0;
        private double actionHOffset = 0;
        private double consVOffset = 0;
        private double consHOffset = 0;

        /// <summary>
        /// Reader to access the workspace to add or edit rule files.
        /// </summary>
        private TextReader ruleFile;

        #endregion

        public AddRules(Window1 main, String rule, TextReader file)
        {
            Owner = main;
            InitializeComponent();
            root = main;
            ruleFile = file;
            if(!string.IsNullOrEmpty(rule))
                nameBox.Text = rule;
            CreateRule.IsDefault = true;
            CancelRule.IsCancel = true;
        }

        /// <summary>
        /// Functionality for editing rules. Items that exist for the specified rule
        /// are checked in the viewing panes.
        /// </summary>
        public void LoadList(object sender, RoutedEventArgs e)
        {
            root.ReloadScriptInfo(sender, e);

            if ((ListBox)sender == SetofCons)   //check if last listbox is loaded
                if (ruleFile != null)
                    for (int i = 0; i < 3; i++)
                    {
                        string line = "";
                        string[] item;

                        line = ruleFile.ReadLine();

                        if (!String.IsNullOrEmpty(line))
                        {
                            item = line.Split('|');

                            foreach (string box in item)
                            {
                                SetofPreconds.SelectedItem = box.Trim();

                                if (i == 0)
                                    for (int j = 0; j < SetofPreconds.Items.Count; ++j)
                                        if (((CheckBox)SetofPreconds.Items.GetItemAt(j)).Content.ToString().Equals(box.Trim()))
                                            ((CheckBox)SetofPreconds.Items.GetItemAt(j)).IsChecked = true;
                                if (i == 1)
                                    for (int j = 0; j < SetofActions.Items.Count; ++j)
                                        if (((CheckBox)(SetofActions.Items.GetItemAt(j))).Content.ToString().Equals(box.Trim()))
                                            ((CheckBox)SetofActions.Items.GetItemAt(j)).IsChecked = true;
                                if (i == 2)
                                    for (int j = 0; j < SetofCons.Items.Count; ++j)
                                        if (((CheckBox)SetofCons.Items.GetItemAt(j)).Content.ToString().Equals(box.Trim()))
                                            ((CheckBox)SetofCons.Items.GetItemAt(j)).IsChecked = true;
                            }
                        }
                    }
        }

        #region Save Rule Functionality

        /// <summary>
        /// Saves the rule with the name specified in the namebox.
        /// </summary>
        private void SaveRuleButton(object sender, RoutedEventArgs e)
        {
            bool valid = false;
            foreach (CheckBox check in SetofActions.Items)
            {
                if (check.IsChecked == true)
                {
                    valid = true;
                    break;
                }
            }

            if (String.IsNullOrEmpty(nameBox.Text))
            {
                SystemSounds.Beep.Play();
                MessageBox.Show("You must specify a name for the new rule.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
            }
            else if (!valid)
            {
                SystemSounds.Beep.Play();
                MessageBox.Show("At least one implication must be specified in a rule.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
            }
            else
            {
                name = nameBox.Text;
                save = "";
                save += savePreconds();
                save += saveActions();
                save += saveCons();
                Close();
            }
        }

        private string savePreconds()
        {
            string s = "";
            SetofPreconds.Dispatcher.Invoke
            (
                (Action)(() =>
                {
                    foreach (CheckBox check in SetofPreconds.Items)
                    {
                        if (check.IsChecked == true)
                            s += check.Content.ToString() + " | ";
                    }

                    if (String.Empty.Equals(s))
                        s = "";
                    else
                    {
                        s = s.Substring(0, s.Length - 3);
                        s += "\n";
                    }
                }));
            return s;
        }

        private string saveActions()
        {
            string s = "";
            SetofActions.Dispatcher.Invoke
            (
                (Action)(() =>
                {
                    foreach (CheckBox check in SetofActions.Items)
                    {
                        if (check.IsChecked == true)
                            s += check.Content.ToString() + " | ";
                    }

                    if (String.Empty.Equals(s))
                        s = "";
                    else
                    {
                        s = s.Substring(0, s.Length - 3);
                        s += "\n";
                    }
                }));
            return s;
        }

        private string saveCons()
        {
            string s = "";
            SetofCons.Dispatcher.Invoke
            (
                (Action)(() =>
                {
                    foreach (CheckBox check in SetofCons.Items)
                    {
                        if (check.IsChecked == true)
                            s += check.Content.ToString() + " | ";
                    }

                    if (String.Empty.Equals(s))
                        s = "";
                    else
                        s = s.Substring(0, s.Length - 3);
                }));
            return s;
        }

        #endregion

        /// <summary>
        /// Cancelation functionality to exit without saving.
        /// </summary>
        private void CancelButton(object sender, RoutedEventArgs e)
        {
            Close();
        }

        #region Scrollbar Functionality

        private void PrecondScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (precondVOffset == e.VerticalOffset && precondHOffset == e.HorizontalOffset)
                return;

            precondVOffset = e.VerticalOffset;
            precondHOffset = e.HorizontalOffset;

            if (precondVOffset != e.VerticalOffset)
                if (SetofPreconds.Parent is ScrollViewer)
                    ((ScrollViewer)SetofPreconds.Parent).ScrollToVerticalOffset(precondVOffset);
            if (precondHOffset != e.HorizontalOffset)
                if (SetofPreconds.Parent is ScrollViewer)
                    ((ScrollViewer)SetofPreconds.Parent).ScrollToVerticalOffset(precondHOffset);
        }

        private void ActionScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (actionVOffset == e.VerticalOffset && actionHOffset == e.HorizontalOffset)
                return;

            actionVOffset = e.VerticalOffset;
            actionHOffset = e.HorizontalOffset;

            if (actionVOffset != e.VerticalOffset)
                if (SetofPreconds.Parent is ScrollViewer)
                    ((ScrollViewer)SetofPreconds.Parent).ScrollToVerticalOffset(actionVOffset);
            if (actionHOffset != e.HorizontalOffset)
                if (SetofPreconds.Parent is ScrollViewer)
                    ((ScrollViewer)SetofPreconds.Parent).ScrollToVerticalOffset(actionHOffset);
        }

        private void ConsScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (consVOffset == e.VerticalOffset && consHOffset == e.HorizontalOffset)
                return;

            consVOffset = e.VerticalOffset;
            consHOffset = e.HorizontalOffset;

            if (consVOffset != e.VerticalOffset)
                if (SetofPreconds.Parent is ScrollViewer)
                    ((ScrollViewer)SetofPreconds.Parent).ScrollToVerticalOffset(consVOffset);
            if (consHOffset != e.HorizontalOffset)
                if (SetofPreconds.Parent is ScrollViewer)
                    ((ScrollViewer)SetofPreconds.Parent).ScrollToVerticalOffset(consHOffset);
        }

        #endregion
    }
}
